package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFormat;
	
	/**
	 * ...
	 * @author patsup
	 * 
	 * 		This is the main game class.
	 * 		GetSS() is used to access the session's stats.
	 * 		RefreshSessionText() mainly used for testing since it displays all the stats.
	 * 
	 * 		Initialize() resets the game's SessionStats data.
	 * 		ResetRound() resets the round, but maintains the game SessionStats data.
	 * 		
	 **********	Potential issues:
	 * 		EndRound() create a new RoundEnd every round... should just display/undisplay it?
	 * 
	 * *** private functions
	 * DrawBackground():void
	 * 
	 * *** protected functions
	 * BackBtnInputMouseClick():void
	 * 
	 * *** public functions
	 * InitNewGame():void
	 * CleanUpRound():void
	 * ResetRound():void
	 * 
	 * TotalNumPirates():int
	 * NumPirates():int
	 * GetPirateValueAt(i:int):int
	 * GetRoundScore():int
	 * GetPlankValues():int
	 * GetDiceValue():int
	 * 
	 * RemovePlank():void
	 * ReturnPlank():void
	 * EnableDice():void
	 * EnableExecute():void
	 * EnablePirates():void
	 * DisablePirates():void
	 * 
	 * EndRound(roundResult:int):void
	 * ExecuteSubRound():void
	 * 
	 * IncreaseBetSize():void
	 * DecreaseBetSize():void
	 * 
	 * RefreshSessionText():void
	 * GetSS():SessionStats
	 * 
	 */
	public class PGame extends Sprite 
	{
		private const NUMBER_OF_PIRATES:int = 9;
		private const NUMBER_OF_DICE:int = 2;
		private const DICE_MAX_VALUE:int = 6;
		private const COLOR:int = 0x87BCF8;						//background image parameters
		private const WIDTH:int = 800;
		private const HEIGHT:int = 480;
		private const EXEC_BUTTON_X_STARTLOC:int = 10;			//Button for Execute
		private const EXEC_BUTTON_Y_STARTLOC:int = 370;
		//private const ROLL_BUTTON_X_STARTLOC:int = 10;			//Button for Roll
		//private const ROLL_BUTTON_Y_STARTLOC:int = 210;
		private const DICE_AREA_X_STARTLOC:int = 250;			//Dice Area
		private const DICE_AREA_Y_STARTLOC:int = 330;
		private const PIRATE_LINEUP_X_STARTLOC:int = 10;		//Pirate Lineup
		private const PIRATE_LINEUP_Y_STARTLOC:int = 25;
		private const PIRATE_PLANK_X_STARTLOC:int = 10;			//Pirate Plank
		private const PIRATE_PLANK_Y_STARTLOC:int = 135;
		private const ROUNDEND_X_STARTLOC:int = 280;				//End of Round screen
		private const ROUNDEND_Y_STARTLOC:int = 210;
		private const BACK_BUTTON_X_STARTLOC:int = 750;			//Button for resign/back to pre-round menu
		private const BACK_BUTTON_Y_STARTLOC:int = 430;
		
		private const SES_STATS_X_STARTLOC:int = 130;			//Session Stats
		private const SES_STATS_Y_STARTLOC:int = 150;
		
		private var diceArea:DiceArea;
		private var execButton:GenButton;
		//private var rollButton:RollButton;
		
		private var pirateLineup:PirateLineup;					//PirateUnits will move between pirateLineup and piratePlank
		private var piratePlank:PiratePlank;
		
		private var roundEnd:NotificationOverlay;							//end of round screen
		public var sesStats:SessionStats;
		
		private var coinTab:CoinTab = new CoinTab();
		private var potTab:PotTab = new PotTab();
		private var coinTabText:TextField;
		private var potTabText:TextField;
		private var tabTxtFormat:TextFormat;
		private const COIN_TAB_TXT_X:int = 75;
		private const COIN_TAB_TXT_Y:int = 10;
		private const POT_TAB_TXT_X:int = 75;
		private const POT_TAB_TXT_Y:int = 10;
		
		
		
		//private var backButton:MenuButton;						//button to give up/return to pre-round menu
		private var backButton:GenButton;						//button to give up/return to pre-round menu
		private var backButtonImgData:ImageData;				//image data to eventually pass to initimage() in menu button
		private const B_BTN_COLOR:int = 0xFF8000;
		private const B_BTN_WIDTH:int = 120;
		private const B_BTN_HEIGHT:int = 40;
		
		private var mainRef:Main;
		private var gameBackground:Game_BackGround;
		
		private var executeSnd:Shot;
		
		private var pirateSndYar:Yar;
		
		private var sounds:Array;
		
		public function PGame(mainRef:Main):void 
		{
			this.mainRef = mainRef;
			gameBackground = new Game_BackGround();
			sounds = new Array();
			executeSnd = new Shot();
			
			pirateSndYar = new Yar();
			
			//sounds.push(mainRef.sounds.addSound(GameMusic));
			
			pirateLineup = new PirateLineup(NUMBER_OF_PIRATES, PIRATE_LINEUP_X_STARTLOC, PIRATE_LINEUP_Y_STARTLOC,mainRef);
			piratePlank = new PiratePlank(PIRATE_PLANK_X_STARTLOC, PIRATE_PLANK_Y_STARTLOC);
			diceArea = new DiceArea(this, NUMBER_OF_DICE, DICE_MAX_VALUE, DICE_AREA_X_STARTLOC, DICE_AREA_Y_STARTLOC);
			//execButton = new GenButton(EXEC_BUTTON_X_STARTLOC, EXEC_BUTTON_Y_STARTLOC, ScrollButton, ExecBtnInputMouseClick, "Execute");
			gameBackground.execute_button.addEventListener(MouseEvent.CLICK, ExecBtnInputMouseClick);
			
			//execButton = new ExecuteButton(this, EXEC_BUTTON_X_STARTLOC, EXEC_BUTTON_Y_STARTLOC);
			//rollButton = new RollButton(this, ROLL_BUTTON_X_STARTLOC, ROLL_BUTTON_Y_STARTLOC);
			//backButtonImgData = new ImageData(BACK_BUTTON_X_STARTLOC, BACK_BUTTON_Y_STARTLOC, "Give Up", B_BTN_COLOR, B_BTN_WIDTH, B_BTN_HEIGHT);
			//backButton = new MenuButton(backButtonImgData, BackBtnInputMouseClick);
			//backButton = new GenButton(BACK_BUTTON_X_STARTLOC, BACK_BUTTON_Y_STARTLOC, Round_Button, BackBtnInputMouseClick);
			gameBackground.main_button.addEventListener(MouseEvent.CLICK, BackBtnInputMouseClick);
			
			sesStats = new SessionStats(this, SES_STATS_X_STARTLOC, SES_STATS_Y_STARTLOC);
			
			//roundEnd = new RoundEnd(this, ROUNDEND_X_STARTLOC, ROUNDEND_Y_STARTLOC);	//not displayed until end of round
			roundEnd = new NotificationOverlay();
			
			pirateLineup.SetOtherLocation(piratePlank);		//set locations so they can communicate with each other
			piratePlank.SetOtherLocation(pirateLineup);
			
			DrawBackground();
			addChild(diceArea);
			addChild(pirateLineup);
			addChild(piratePlank);
			//addChild(execButton);
			//addChild(backButton);
			//addChild(sesStats);	//removed here temporarily?
			//addChild(rollButton);
		}
		
		
		private function ExecBtnInputMouseClick(e:MouseEvent):void
		{
			//check the plank to see if it matches the dice
			if (GetPlankSum() != GetDiceValue())
			{
				trace ("Execute:" + GetPlankSum() + "=" + GetDiceValue() + "? Fail:No match!");
				ReturnPlank();									//return them to the lineup
			} else {
				trace("Execute:" + GetPlankSum() + "=" + GetDiceValue() + "? Success!");
				dispatchEvent(new AchievementEvent(AchievementEvent.EXECUTED_PLANK, GetPlankValues()));
				
				RemovePlank();									//execute the pirates
				EnableDice();									//reset dice (enable to be clickable, start'em spinnin)
				//execButton.DisableButton();						//don't let execute be clickable
				gameBackground.execute_button.removeEventListener(MouseEvent.CLICK, ExecBtnInputMouseClick);
				DisablePirates();								//don't let pirates left on lineup be clickable
				if (NumPirates() == 0) {						//check end game state
					EndRound(1);								// <<<END OF ROUND>>>  1 = round won
				}
				RefreshSessionText();							//update txt on session stats
				//sounds.push(mainRef.sounds.addSound(ExecuteSnd));
			}
		}
		
		
		//DrawBackground()
		//draw a non-interactable background of the game/play area
		private function DrawBackground():void
		{
			graphics.beginFill(COLOR);
			graphics.drawRect(0, 0, WIDTH, HEIGHT);
			graphics.endFill();
			//var _bigShipImg:Big_Ship = new Big_Ship();
			//_bigShipImg.x = 400;
			//_bigShipImg.y = 50;
			//_bigShipImg.width = 1200;
			//_bigShipImg.height = 400;
			//addChild(_bigShipImg);
			
			addChild(gameBackground);
			
			coinTab = new CoinTab();
			potTab = new PotTab();
			coinTabText = new TextField();
			potTabText = new TextField();
			tabTxtFormat = new TextFormat();
			tabTxtFormat.size = 20;
			tabTxtFormat.color = 0xE0E0E0;
			coinTabText.x = COIN_TAB_TXT_X;
			coinTabText.y = COIN_TAB_TXT_Y;
			potTabText.x = POT_TAB_TXT_X;
			potTabText.y = POT_TAB_TXT_Y;
			coinTab.x = 550;
			coinTab.y = 370;
			potTab.x = 550;
			potTab.y = 415;
			coinTab.addChild(coinTabText);
			potTab.addChild(potTabText);
			addChild(coinTab);
			addChild(potTab);
		}
		
		public function getMainRef():Main
		{
			return mainRef;						//so achievements can talk to main (tell it to add event listeners)
		}
		//InitNewGame()
		public function InitNewGame():void
		{
			sesStats.InitNewGame();
		}
		//InitLoadGame()
		public function InitLoadGame(data:Object):void
		{
			//sesStats.InitNewGame();
			sesStats.InitLoadGame(data);
		}
		
		//CleanUpRound()
		//called at the end of a round (between RoundEnd and PreRoundMenu)
		public function CleanUpRound(e:MouseEvent):void
		{
			removeChild(roundEnd);
			mainRef.ContinueNewRound();
			
			sesStats.UpdateText();	//here temporarily to see stats
		}
		
		//ResetRound()
		//called at beginning of round to reset round, continuing game.... just before you display (addchild) the game
		public function ResetRound():void
		{
			pirateLineup.Initialize(NUMBER_OF_PIRATES);
			piratePlank.Initialize();	//to remove any additional pirates just in case...
			diceArea.Initialize();
			//execButton.Initialize();
			gameBackground.execute_button.addEventListener(MouseEvent.CLICK, ExecBtnInputMouseClick);
			
			//backButton.EnableButton();	//re-enable back button
			gameBackground.main_button.addEventListener(MouseEvent.CLICK, BackBtnInputMouseClick);
			sesStats.ApplyRoundStart();
			UpdateText();				//update totalmoney and currentbet text
			
			//if(mainRef.DEBUG_MODE) addChild(sesStats);	//added here temporarily?
		}
	
		//no longer used
		private function UpdateText():void
		{
			coinTabText.text = sesStats.GetTotalMoney().toString();
			potTabText.text = sesStats.GetCurrentBetSize().toString();
			coinTabText.setTextFormat(tabTxtFormat);
			potTabText.setTextFormat(tabTxtFormat);
		}
		
		//NumPirates()
		//only returns number of pirates in the lineup, for use in subset() in DiceArea
		//btw, piratePlank should have 0 pirates in it when this is called anyways...
		public function NumPirates():int
		{
			return pirateLineup.NumPirates();
		}
		public function GetPirateValueAt(i:int):int {
			return pirateLineup.GetPirateValueAt(i);
		}
		public function GetRoundScore():int {
			return pirateLineup.GetPirateSum();
		}
		public function GetPlankSum():int {
			return piratePlank.GetPirateSum();
		}
		public function GetPlankValues():Vector.<int> {
			return piratePlank.GetPirateValues();
		}
		public function GetLineupValues():Vector.<int> {
			return pirateLineup.GetPirateValues();
		}
		public function RemovePlank():void {
			piratePlank.RemovePirates();
		}
		public function ReturnPlank():void {
			piratePlank.ReturnPirates();
		}
		public function GetDiceValue():int {
			return diceArea.GetDiceValue();
		}
		public function EnableDice():void {
			diceArea.StartRollingDice();		//make the images start "rolling"
			diceArea.EnableButton();
		}
		public function EnableExecute():void {
			//execButton.EnableButton();
			gameBackground.execute_button.addEventListener(MouseEvent.CLICK, ExecBtnInputMouseClick);
			
		}
		public function EnablePirates():void {
			pirateLineup.EnableButtons();
		}
		public function DisablePirates():void {
			pirateLineup.DisableButtons();
		}
		//public function EnableRoll():void
		//{
			//rollButton.EnableButton();
		//}
		//EndRound()
		//called at the end of a round (whether from winning, losing, or resigning)
		//tell SessionStats to update the stats: ApplyRoundEnd()
		public function EndRound(roundResult:int):void
		{
			//1 = round won, 0 = round lost
			
			//roundEnd.DisplayImage(roundResult);
			DisplayRoundEnd(roundResult);
			
			diceArea.DisableButton();
			//execButton.DisableButton();
			gameBackground.execute_button.addEventListener(MouseEvent.CLICK, ExecBtnInputMouseClick);
			//rollButton.DisableButton();
			pirateLineup.DisableButtons();
			piratePlank.DisableButtons();
			//backButton.DisableButton();
			gameBackground.main_button.removeEventListener(MouseEvent.CLICK, BackBtnInputMouseClick);
			
			
			addChild(roundEnd);
			roundEnd.addEventListener(MouseEvent.CLICK, CleanUpRound);
			
			sesStats.ApplyRoundEnd();
			//sesStats.GetAchievements().GetDataAsString();
			
			mainRef.SaveGame();			//tell main to save session data to its saveData:SharedObject
		}
		
		private function DisplayRoundEnd(roundWon:Boolean):void {
			roundEnd.ach_icon.visible = false;
			roundEnd.bust_icon.visible = true;
			roundEnd.bust_icon.gotoAndStop(mainRef.playerIndex);
			roundEnd.header.text = "";
			
			if (roundWon) {
				roundEnd.header.text = "Perfect! ";
			}
			
			
			var _winnings:int = sesStats.CalcWinningsWithBetAndScore();
			var _betSize:int = sesStats.GetCurrentBetSize();
			if (_winnings > 0) {
				roundEnd.header.text = "Good Job!";
				roundEnd.desc.text = "You won $" + _winnings;
			} else if (_winnings == 0) {
				roundEnd.header.text = "Almost turned a profit!";
				roundEnd.desc.text = "You broke even.";
				
				//dispatchEvent(new AchievementEvent(AchievementEvent.BREAK_EVEN));
			} else {
				roundEnd.header.text = "Well, you tried...";
				roundEnd.desc.text = "You lost $" + _betSize;
				//btnLabel.appendText("\nBetter luck next time.  You lost your bet of $" + _betSize );
			}
			
			roundEnd.second.text = "Score: " + String(GetRoundScore() + "\n");
			
			//"You won $" + _winnings);
		}
		
		public function RefreshSessionText():void
		{
			sesStats.UpdateText();
		}
		
		//BackBtnInputMouseClick()
		//called on back button mouse click which is the forfeit/resign button
		protected function BackBtnInputMouseClick(e:MouseEvent):void
		{
			//backButton.DisableButton();
			gameBackground.main_button.removeEventListener(MouseEvent.CLICK, BackBtnInputMouseClick);
			diceArea.StopRollingDice();
			ReturnPlank();
			//dispatchEvent(new AchievementEvent(AchievementEvent.FORFEIT));
			EndRound(0);
		}
		
		public function IncreaseBetSize():void
		{
			sesStats.IncrBetSize();
		}
		public function DecreaseBetSize():void
		{
			sesStats.DecrBetSize();
		}
		public function GetSS():SessionStats
		{
			return sesStats;
		}
		//TotalNumPirates()
		//Need to know this to calculate payout tiers in session stats class
		public function TotalNumPirates():int
		{
			return NUMBER_OF_PIRATES;
		}
		
	}
	
}